/* eslint valid-jsdoc: "off" */

'use strict';

/**
 * @param {Egg.EggAppInfo} appInfo app info
 */
module.exports = appInfo => {
  /**
     * built-in config
     * @type {Egg.EggAppConfig}
     **/
  const config = exports = {};

  // use for cookie sign key, should change to your own and keep security
  config.keys = appInfo.name + '_1595823950776_8665';

  // add your middleware config here , 处理每一次请求
  config.middleware = [
    // 配置需要的中间件，数组顺序即为中间件的加载顺序
    // 'auth',
    'gzip',
    'notfoundHandler', // 引入notfound中间件
  ];
  // match 和 ignore 支持多种类型的配置方式：
  // 字符串：当参数为字符串类型时，配置的是一个 url 的路径前缀，所有以配置的字符串作为前缀的 url 都会匹配上。 当然，你也可以直接使用字符串数组。
  // 正则：当参数为正则时，直接匹配满足正则验证的 url 的路径。
  // 函数：当参数为一个函数时，会将请求上下文传递给这个函数，最终取函数返回的结果（true/false）来判断是否匹配。
  config.gzip = {
    threshold: 1024, // 小于 1k 的响应体不压缩
    // threshold: 1, // 小于 1k 的响应体不压缩
    // ignore: '/api',   // string will use parsed by path-to-regexp
    // match: '/static', //针对static静态资源才压缩
    match(ctx) {
      // 只有 ios 设备才开启
      const reg = /iphone|ipad|ipod/i;
      return reg.test(ctx.get('user-agent'));
    },
  };


  // 设置上传文件（有file，stream），用file模块
  config.multipart = {
    mode: 'file',
    fileExtensions: [ '.apk' ], // 增加对 apk 扩展名的文件支持
    // whitelist: [ '.png' ], // 覆盖整个白名单，只允许上传 '.png' 格式 , 注意：当重写了 whitelist 时，fileExtensions 不生效。
  };

  // add your user config here
  const userConfig = {
    // myAppName: 'egg',
  };

  // 设置默认模板引擎
  config.view = {
    defaultViewEngine: 'nunjucks',
    mapping: {
      '.html': 'nunjucks',
    },
  };

  // 关闭 csrf
  config.security = {
    csrf: false,
    // csrf: {
    //     queryName: '_csrf', // 通过 query 传递 CSRF token 的默认字段为 _csrf
    //     bodyName: '_csrf', // 通过 body 传递 CSRF token 的默认字段为 _csrf
    //     headerName: 'x-csrf-token', // 通过 header 传递 CSRF token 的默认字段为 x-csrf-token

    //     useSession: true, // 默认为 false，当设置为 true 时，将会把 csrf token 保存到 Session 中
    //     cookieName: 'csrfToken', // Cookie 中的字段名，默认为 csrfToken
    //     sessionName: 'csrfToken', // Session 中的字段名，默认为 csrfToken
    //   },
  };


  // 定时器的日志设置输出到控制台
  config.customLogger = {
    scheduleLogger: {
      // consoleLevel: 'NONE',
      // file: path.join(appInfo.root, 'logs', appInfo.name, 'egg-schedule.log'),
    },
  };

  // 框架提供了一个 renew 配置项用于实现此功能，它会在发现当用户 Session 的有效期仅剩下最大有效期一半的时候，重置 Session 的有效期。
  config.session = {
    key: 'EGG_SESS_HAHA',
    maxAge: 24 * 3600 * 1000, // 1 天
    httpOnly: true,
    encrypt: true,

    renew: true,
  };

  // 定制错误时，跳转到的页面
  config.onerror = {
    // 线上页面发生异常时，重定向到这个页面上
    // errorPageUrl: '/50x.html',
    // all(err, ctx) {
    //     // 在此处定义针对所有响应类型的错误处理方法
    //     // 注意，定义了 config.all 之后，其他错误处理方法不会再生效
    //     ctx.body = 'error';
    //     ctx.status = 500;
    // },
    // html(err, ctx) {
    //     // html hander
    //     ctx.body = '<h3>error</h3>';
    //     ctx.status = 500;
    // },
    // json(err, ctx) {
    //     // json hander
    //     ctx.body = { message: 'error' };
    //     ctx.status = 500;
    // },
    // jsonp(err, ctx) {
    //     // 一般来说，不需要特殊针对 jsonp 进行错误定义，jsonp 的错误处理会自动调用 json 错误处理，并包装成 jsonp 的响应格式
    // },
  };

  // config.notfound = {
  //     pageUrl: '/404.html',
  // }

  config.security = {
    csrf: {
      useSession: true, // 默认为 false，当设置为 true 时，将会把 csrf token 保存到 Session 中
      cookieName: 'csrfToken', // Cookie 中的字段名，默认为 csrfToken
      sessionName: 'csrfToken', // Session 中的字段名，默认为 csrfToken
    },

    // 若用户没有配置 domainWhiteList 或者 domainWhiteList数组内为空，则默认会对所有跳转请求放行，即等同于ctx.unsafeRedirect(url)
    domainWhiteList: [ '.baidu.com' ], // 安全白名单，以 . 开头  ,后续可以用 ctx.redirect(url)

    ssrf: {
      ipBlackList: [
        '10.0.0.0/8', // 支持 IP 网段
        '0.0.0.0/32',
        '127.0.0.1', // 支持指定 IP 地址
      ],
      // 配置了 checkAddress 时，ipBlackList 不会生效
      checkAddress(ip) {
        return ip !== '127.0.0.1';
      },
    },
  };

  config.mysql = {
    // 单数据库信息配置
    client: {
      // host
      host: '127.0.0.1',
      // host: 'localhost',
      // 端口号
      port: '3306',
      // 用户名
      user: 'root',
      // 密码
      password: 'root',
      // 数据库名
      database: 'wp',
    },
    // 是否加载到 app 上，默认开启
    app: true,
    // 是否加载到 agent 上，默认关闭
    agent: false,
  };

  // 配置 sequelize 插件，注意database里 config.json 的账号密码不能加载到
  config.sequelize = {
    dialect: 'mysql', // 数据库类型
    timezone: '+08:00', // 保存为本地时区
    database: config.mysql.client.database, // 'wp', //数据库名称
    host: config.mysql.client.host, // '127.0.0.1', //数据库ip地址
    port: config.mysql.client.port, // '3306', //数据库端口
    username: config.mysql.client.user, // 'root', //数据库用户名
    password: config.mysql.client.password, // 'root' //数据库密码

    // 让读取date类型数据时返回字符串而不是UTC时间
    dialectOptions: {
      dateStrings: true,
      typeCast: true,
    },
    // dialectOptions: {  // 让读取date类型数据时返回字符串而不是UTC时间
    //     dateStrings: true,
    //     typeCast(field, next) {
    //         if (field.type === "DATETIME") {
    //             return field.string();
    //         }
    //         return next();
    //     }
    // },
    define: { // model的全局配置
      timestamps: false, // 添加 create,update,delete时间戳
      // paranoid: true, // 添加软删除
      freezeTableName: true, // 防止修改表名为复数
      underscored: false, // 防止驼峰式字段被默认转为下划线
    },

  };


  // 用户输入表单的验证
  config.validate = { // 配置参数校验器，基于parameter
    convert: true, // 对参数可以使用convertType规则进行类型转换
    // validateRoot: false,   // 限制被验证值必须是一个对象。
  };

  // 定时器schedule的定时时间
  config.cacheTick = '1m';


  // egg-socket.io  https://www.jianshu.com/p/9f79fd9c81f6
  config.io = {

    // 配置1
    // init: {}, // passed to engine.io
    // namespace: {
    //     '/': {
    //         connectionMiddleware: [],
    //         packetMiddleware: [],
    //     },
    //     '/news': {
    //         connectionMiddleware: [],
    //         packetMiddleware: [],
    //     },
    // },


    // 配置2
    // namespace命名空间配置为/
    namespace: {
      '/': {
        // 预处理器中间件, 我们这里配置了一个auth, 进行权限判断, 它对应的文件是/app/io/middleware/auth.js, 这里可以配置多个文件, 用逗号隔开
        connectionMiddleware: [ 'auth', 'check' ], // 这里我们可以做一些权限校验之类的操作
        packetMiddleware: [ 'filter' ], // 通常用于对消息做预处理，又或者是对加密消息的解密等操作
      },
    },
    generateId: req => { // 自定义 socket.id 生成函数
      return Math.round(Math.random(10000) * 10000, 4);
      // const data = qs.parse(req.url.split('?')[1]);
      // return data.userId; // custom id must be unique
    },
    // 配置redis, 非必须, 不需要的可以不配置这块, egg-socket.io内置了socket-io-redis， 在cluster模式下, 使用redis可以较为简单的实现clients/rooms等信息共享
    // redis: {
    //   host: 'ip地址',
    //   prot: 6379,
    //   auth_pass: 123456,
    //   db:0,
    // }
  };


  return {
    ...config,
    ...userConfig,
  };
};
